﻿namespace Lucid.ESA.ClientDataSystem.Domain.Common
{
    /// <summary>
    /// Base for an Entity. Overrides Equals() and GetHashCode() according to NHibernate specifications.
    /// </summary>
    public class Entity
    {
        protected long? _id;
        protected int? _hashCode;

        public virtual long? Id
        {
            get { return _id; }
            set { _id = value; }
        }

        /// <summary>
        /// Override of Equals according to NHibernate specification.
        /// </summary>
        /// <param name="obj">Object to compare.</param>
        /// <returns>True if objects are logically equal.</returns>
        public override bool Equals(object obj)
        {
            Entity other = obj as Entity;

            //If other is null then it is either null to begin with or it was of incorrect type.
            if (other == null) return false;

            //If both are transient, need to go off memory reference.
            if (!other.Id.HasValue && !_id.HasValue)
                return other == this;

            //If one is transient and the other isn't then they are not the same.
            if (!other.Id.HasValue || !_id.HasValue)
                return false;

            return other.Id.Value == _id.Value;
        }

        /// <summary>
        /// Override of GetHashCode accoriding to NHibernate specification.
        /// </summary>
        /// <returns>The HashCode.</returns>
        public override int GetHashCode()
        {
            //Once we have a hash code we'll never change it.
            if (_hashCode.HasValue)
                return _hashCode.Value;

            //When this instance is transient, we use the base GetHashCode()
            //and remember it, so an instance can NEVER change its hash code.
            if (!_id.HasValue)
            {
                _hashCode = base.GetHashCode();
                return _hashCode.Value;
            }

            return _id.GetHashCode();
        }
    }
}
